import { Component, inject, OnInit } from '@angular/core';
import { TreeModule } from 'primeng/tree';
import { TreeDragDropService, ConfirmationService } from 'primeng/api';
import { ProgressBarModule } from 'primeng/progressbar';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { InputTextModule } from 'primeng/inputtext';
import { InputNumberModule } from 'primeng/inputnumber';
import { FormsModule } from '@angular/forms';
import { CheckboxModule } from 'primeng/checkbox';
import { DialogModule } from 'primeng/dialog';
import { ButtonModule } from 'primeng/button';
import { ContextMenuModule } from 'primeng/contextmenu';
import { MenuItem } from 'primeng/api';
import { DatePickerModule } from 'primeng/datepicker';
import { TrackLineService } from '../service/track-line.service';
import { TauriService } from '../service/tauri.service';
import { SrtmService } from '../service/srtm.service';
import { TransformService } from '../service/transform.service';
import { EditTrackLine } from '../data-model/edit-track-line.model';
import { g } from '../service/global-data'

@Component({
    selector: 'app-track-edit',
    imports: [TreeModule, ProgressBarModule, ContextMenuModule, ConfirmDialogModule, DialogModule, ButtonModule, DatePickerModule,
        InputTextModule, InputNumberModule, CheckboxModule, FormsModule],
    providers: [ConfirmationService, TreeDragDropService],
    templateUrl: './track-edit.html',
    styleUrl: './track-edit.css',
})
export class TrackEdit implements OnInit {
    dom: any;
    disable = () => g.editing ? '' : 'disabled';
    track_line_list: any[] = [];
    selected_track_line: EditTrackLine | null = null;
    confirmationService = inject(ConfirmationService);
    trackLineService = inject(TrackLineService);
    tauriService = inject(TauriService);
    srtmService = inject(SrtmService);
    transformService = inject(TransformService);

    context_menu_items: MenuItem[] = [
        {
            label: '重命名',
            command: (event) => {
                this.rename_track_name = this.selected_track_line!.label!;
                this.show_rename_track_dialog = true;
            },
        },
        {
            separator: true,
        },
        {
            label: '移动至<用户数据>',
            command: (event) => {
                this.move_to_user_data();
            },
        },
        {
            separator: true,
        },
        {
            label: '填充高程数据',
            command: (event) => {
                this.fill_track_line_altitudes();
            },
        },
        {
            separator: true,
        },
        {
            label: '删除高程数据',
            command: (event) => {
                this.delete_track_line_altitudes();
            },
        },
        {
            separator: true,
        },
        {
            label: '轨迹起始点翻转',
            command: (event) => {
                this.reverse_track_line();
            },
        },
        {
            separator: true,
        },
        {
            label: '删除轨迹',
            command: (event) => {
                g.header.delete_track_line();
            },
        },
    ];

    rename_track_name = '';
    show_rename_track_dialog = false;

    show_strm_download_dialog = false;
    strm_download_progress = 0;
    strm_download_tip = '';

    show_track_point_edit_dialog = false;
    edit_current_point: number[] = [];
    edit_current_point_time = new Date();

    ngOnInit(): void {
        g.track_edit = this;

        this.dom = document.getElementById('track-edit')!
        this.dom.addEventListener('contextmenu', (event: any) => {
            event.preventDefault();
        });
    }

    onNodeDrop(event: any) {
        const dragNode = event.dragNode;
        const dropNode = event.dropNode;

        const indexDropNode = this.track_line_list.indexOf(dropNode);
        this.track_line_list.splice(indexDropNode, 0, dragNode);
        delete dropNode.children;

        g.header.undo_list = [];
    }

    onNodeSelect(event: any) {
        for (const track_line of this.track_line_list) {
            track_line.selected = false;
        }
        this.selected_track_line!.selected = true;

        g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    // 默认再点击已选择节点后取消选择，禁用此功能
    onNodeUnselect(event: any) {
        const that = this;
        function wait_unselect_complete() {
            setTimeout(() => {
                if (!!that.selected_track_line) {
                    wait_unselect_complete();
                } else {
                    that.selected_track_line = event.node;
                    that.selected_track_line!.selected = true;
                    // 因为存在点击checkbox引起的状态变化，所以需要刷新
                    g.map_canvas.repaint();
                    g.track_chart.refresh();
                    g.track_info.refresh();
                }
            }, 10);
        }

        // 取消选择后有延时，需等待完成
        wait_unselect_complete();
    }

    async onNodeDoubleClick(event: any) {
        this.selected_track_line = event.node;
        g.map_canvas.zoom_to_track(this.selected_track_line);
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    select_track_line(track_line_uuid: string) {
        this.selected_track_line = null;

        for (const track_line of this.track_line_list) {
            if (track_line.uuid === track_line_uuid) {
                this.selected_track_line = track_line;
                track_line.selected = true;
            } else {
                track_line.selected = false;
            }
        }

        g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    onNodeContextMenuSelect(event: any) {
        this.selected_track_line = event.node;
        g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    reverse_track_line() {
        const track_line = this.selected_track_line;

        if (!track_line) return;

        const that = this;
        function do_reverse() {
            track_line!.points!.reverse();
            track_line!.has_timestamp = false;

            g.map_canvas.repaint();
            g.track_chart.refresh();
            g.track_info.refresh();
        }

        if (track_line.has_timestamp) {
            this.confirmationService.confirm({
                header: '该轨迹含时间戳信息，翻转后时间信息将丢失。确定翻转？',
                message: track_line.label,
                icon: 'pi pi-exclamation-triangle',
                rejectButtonProps: {
                    label: '否',
                    severity: 'secondary',
                    outlined: true,
                },
                acceptButtonProps: {
                    label: '是',
                    severity: 'danger',
                },
                accept: () => {
                    do_reverse();
                },
                reject: () => { },
            });
        } else {
            do_reverse();
        }
    }


    delete_track_line_altitudes() {
        const track_line = this.selected_track_line;

        if (!track_line) return;

        this.confirmationService.confirm({
            header: '确定要删除该轨迹中所有轨迹点的高程数据？注意：此操作不可逆转！！！',
            message: track_line.label,
            icon: 'pi pi-exclamation-triangle',
            rejectButtonProps: {
                label: '否',
                severity: 'secondary',
                outlined: true,
            },
            acceptButtonProps: {
                label: '是',
                severity: 'danger',
            },
            accept: () => {
                for (const point of track_line.points!) {
                    point[2] = 0;
                }

                this.trackLineService.compute_track_line_args(track_line);
                // g.map_canvas.repaint();
                g.track_chart.refresh();
                g.track_info.refresh();
            },
            reject: () => { },
        });
    }

    async fill_track_line_altitudes() {
        const track_line = this.selected_track_line;
        if (!track_line) return;

        this.strm_download_progress = 0;
        this.strm_download_tip = '';
        this.show_strm_download_dialog = true;

        const progress_step = Math.floor(100 / track_line.point_num!);
        for (let i = 0; i < track_line.points!.length; i++) {
            this.strm_download_tip = `下载第 ${i} 个轨迹点的高程数据......`
            const point = track_line.points![i];
            if (point[2] <= 0) {
                point[2] = await this.srtmService.get_alt(point[0], point[1]);
            }
            this.strm_download_progress += progress_step;
        }

        this.strm_download_progress = 100;
        this.strm_download_tip = '高程数据填充完毕！';
        this.show_strm_download_dialog = false;

        this.trackLineService.compute_track_line_args(track_line);
        // g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    move_to_user_data() {
        const track_line = this.selected_track_line;
        g.track_line_points_cache.set(track_line!.uuid, track_line!.points);
        this.tauriService.save_track_data(track_line!.uuid!);

        this.selected_track_line = null;
        this.track_line_list.splice(this.track_line_list.indexOf(track_line), 1);

        this.trackLineService.delete_edit_track_line_extra_fields(track_line!);
        g.root_node_list.push(track_line);
        g.visible_tracks.set(track_line!.uuid, track_line);

        g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

    edit_track_line_point() {
        this.edit_current_point = structuredClone(this.selected_track_line!.points![this.selected_track_line!.selected_point!]);
        this.edit_current_point_time = new Date(this.edit_current_point[3]);
        this.show_track_point_edit_dialog = true;
    }

    has_prev_point() {
        return this.selected_track_line!.selected_point! > 0;
    }

    has_next_point() {
        return this.selected_track_line!.selected_point! < this.selected_track_line!.point_num! - 1;
    }

    compute_current_point_mean_alt() {
        let result;
        if (this.has_prev_point() && this.has_next_point()) {
            result = (this.selected_track_line!.points![this.selected_track_line!.selected_point! - 1][2]
                + this.selected_track_line!.points![this.selected_track_line!.selected_point! + 1][2]) / 2;
        } else if (!this.has_prev_point() && this.has_next_point()) {
            result = (this.edit_current_point[2]
                + this.selected_track_line!.points![this.selected_track_line!.selected_point! + 1][2]) / 2;
        } else if (this.has_prev_point() && !this.has_next_point()) {
            result = (this.edit_current_point[2]
                + this.selected_track_line!.points![this.selected_track_line!.selected_point! - 1][2]) / 2;
        } else {
            result = this.edit_current_point[2];
        }

        this.edit_current_point[2] = result;
    }

    edit_to_prev_point() {
        if (this.selected_track_line!.selected_point! > 0) {
            this.selected_track_line!.selected_point! --;
            this.edit_current_point = structuredClone(this.selected_track_line!.points![this.selected_track_line!.selected_point!]);
            this.edit_current_point_time = new Date(this.edit_current_point[3]);
            g.map_canvas.repaint();
            g.track_chart.refresh();
            g.track_info.refresh();
        }
    }

    edit_to_next_point() {
        if (this.selected_track_line!.selected_point! < this.selected_track_line!.point_num! - 1) {
            this.selected_track_line!.selected_point! ++
            this.edit_current_point = structuredClone(this.selected_track_line!.points![this.selected_track_line!.selected_point!]);
            this.edit_current_point_time = new Date(this.edit_current_point[3]);
            g.map_canvas.repaint();
            g.track_chart.refresh();
            g.track_info.refresh();
        }
    }

    update_track_line_point() {
        this.selected_track_line!.points![this.selected_track_line!.selected_point!][2] = this.edit_current_point[2]
        this.selected_track_line!.points![this.selected_track_line!.selected_point!][3] = this.edit_current_point_time.toISOString();

        this.trackLineService.compute_track_line_args(this.selected_track_line!);
        g.map_canvas.repaint();
        g.track_chart.refresh();
        g.track_info.refresh();
    }

}

